package middleware

import (
	"strconv"
	"strings"
	"team-evaluate/global"
	"team-evaluate/pkg/app"
	"team-evaluate/pkg/errcode"

	"github.com/go-redis/redis"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
)

// JWT 基于JWT的认证中间件
func JWT() gin.HandlerFunc {
	return func(c *gin.Context) {
		var (
			token string
			ecode = errcode.Success
		)
		// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
		// 这里假设Token放在Header的Authorization中，并使用Bearer开头
		// 这里的具体实现方式要依据你的实际业务情况决定
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == "" {
			ecode = errcode.UnauthorizedAuthNotExist
		} else {
			// 按空格分割
			parts := strings.SplitN(authHeader, " ", 2)
			if !(len(parts) == 2 && parts[0] == "Bearer") {
				ecode = errcode.UnauthorizedAuthFormatError
			} else {
				token = parts[1]
				mc, err := app.ParseToken(token)
				if err != nil {
					switch err.(*jwt.ValidationError).Errors {
					case jwt.ValidationErrorExpired:
						ecode = errcode.UnauthorizedTokenTimeout
					default:
						ecode = errcode.UnauthorizedTokenError
					}
				}
				if mc != nil {
					// 为了限制账号同一时间只能登录一台设备，这里可以使用mc.UserId去redis里查找对应的token
					// 找到之后和现有的token进行对比，如果不一样，就返回鉴权失败，重新登录
					// 预留
					val, err := global.RDb.Get("token:" + mc.UserId).Result()
					if err == redis.Nil {
						ecode = errcode.UnauthorizedTokenRedis
					} else if err != nil {
						global.Logger.Errorf("rdb.Get err: %v", err)
					} else {
						if val != token {
							ecode = errcode.UnauthorizedTokenRedis
						}
					}

					id, err := strconv.Atoi(mc.UserId)
					if err == nil {
						c.Set("userId", uint32(id))
					}

				}

			}
		}
		if ecode != errcode.Success {
			response := app.NewResponse(c)
			response.ToErrorResponse(ecode)
			c.Abort()
			return
		}
		c.Next()
	}
}
